package com.consumer.web;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author xiangminwen
 * @since 2022/11/23 17:53
 */
public class JacksonUtil {

    private final static Logger LOG = LoggerFactory.getLogger(JacksonUtil.class);
    public static final ObjectMapper MAPPER;

    static {
        MAPPER = new ObjectMapper();
        //默认非空不输出
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //空对象不要抛异常
        MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //反序列化时，属性不存在的兼容处理
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    public static String toJson(Object obj) {
        try {
            return MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            LOG.error("toJson error", e);
            throw new RuntimeException(e);
        }
    }

    public static <T> List<T> toList(String json, Class<T> clazz) {
        try {
            if (StringUtils.isEmpty(json)) {
                return null;
            }
            JavaType javaType = getCollectionType(ArrayList.class, clazz);
            return MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            LOG.error("toList error", e);
            throw new RuntimeException(e);
        }
    }

    public static <T> Map<String, T> toMap(String json, Class<T> clazz) {
        try {
            if (StringUtils.isEmpty(json)) {
                return null;
            }
            JavaType javaType = getCollectionType(HashMap.class, String.class, clazz);
            return MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            LOG.error("toMap error", e);
            throw new RuntimeException(e);
        }
    }

    public static <T> T fromObj(String json, Class<T> clazz) {
        try {
            if (StringUtils.isEmpty(json)) {
                return null;
            }
            return MAPPER.readValue(json, clazz);
        } catch (Exception e) {
            LOG.error("fromObj error", e);
            throw new RuntimeException(e);
        }
    }

    private static JavaType getCollectionType(Class<?> parametrized, Class<?>... parameterClass) {
        return MAPPER.getTypeFactory().constructParametricType(parametrized, parameterClass);
    }
}